/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package server;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.HashMap;
import datagram.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author rmb
 */
public class DataReceive extends Thread{
    
    private DatagramSocket socket;
    private String ip;
    private boolean stop;
    private HashMap<Integer,byte[]> object;
    private String filename;    
    private int expected_packs;
    private int received_packs;
    private boolean finished;

    public DataReceive(DatagramSocket socket) {
        this.socket = socket;
        stop = false;
        object = new HashMap<Integer, byte[]>();
        filename = "someFile";
        expected_packs = 0;
        received_packs = 0;
        finished = false;
    }
    
    
    @Override
    public void run() {
        
        while(!stop) {
            
            byte[] buffer = new byte[512];
            DatagramPacket pack = new DatagramPacket(buffer, 512);
            try {
                socket.receive(pack);
            }
            catch(IOException e) {}

            Datagram d = Datagram.byteToDatagram(buffer);
            
            switch(d.getType()) {
                
                
                case DATA_TRANSFER :
                    Server.getChannel().getConnection(ip).getSend().incExpectedNum(d.getPack_num());
                    placeInObject(d.getPack_num(), d.getData());
                    received_packs++;
                    break;
                
                case FILENAME :
                    filename = (String) Datagram.byteToObject(d.getData());
                    expected_packs = d.getPack_num();
                    System.out.println(filename);
                    break;
                
                case STOP_DATA_TRANSFER :
                    Server.getChannel().getConnection(ip).getSend().incExpectedNum(d.getPack_num());
                    placeInObject(d.getPack_num(),d.getData());
                    received_packs++;
                    writeObjectToFile(createObject(), filename);
                
                case DISCONNECT :
                    if(finished) {
                        Server.getChannel().deleteCon(ip);
                    }
                    else {
                        Server.getChannel().getConnection(ip).getSend().sendDISCONECT();
                        Server.getChannel().deleteCon(ip);
                    }
                    
                default:
                    System.out.println("Error: Unknown packet");
                    
            }
            
        }
        
        
    }
    
    public void placeInObject(int pack_num,byte[] buff) {
        object.put(pack_num, buff);
    }
    
    public byte[] createObject() {
        int finalSize = 0;
        
        
        for(byte[] buf : object.values()) {
            finalSize += buf.length;
        }
        
        byte[] obj = new byte[finalSize];
        finalSize = 0;        
        
        for(int i = 0; i < object.keySet().size(); i++) {
            
            byte[] tmp = object.get(i);
            for(i = 0; i < tmp.length; i++ , finalSize++) {
                obj[finalSize] = tmp[i];
            }
            
        }
        
        return obj;
    }
    
    public File writeObjectToFile(byte[] obj, String filename) {
         
        File file = new File(filename);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
        } catch (FileNotFoundException e) {}            
        try {
        fos.write(obj);
        fos.flush();
        fos.close();
        }
        catch(IOException e) {}

        return file;
    }

    public int getExpected_packs() {
        return expected_packs;
    } 

    public int getReceived_packs() {
        return received_packs;
    }
    
    public synchronized void setStop() {
        this.stop = true;
    }

    public void setFinished() {
        this.finished = true;
    }
    
    
    
    
    
}
